package ru.pbem.olympia.battles;

import ru.pbem.olympia.utils.RandomAccessIterator;
import ru.pbem.olympia.utils.RandomAccessListIterator;

import java.util.List;
import java.util.Random;

/**
 * User: roman.pavlov
 * Date: 21-Sep-2010
 * Time: 18:28:54
 */
public class G3Battle implements Battle<Army> {
    @Override
    public Army fight(final Army attacker, final Army defender) {
        Army winner;
        do {
            winner = round(attacker, defender);
        } while (winner == null);
        return winner;
    }

    protected Army round(final Army attacker, final Army defender) {
        final RandomAccessIterator<FightingUnit> aAttackersIt = new RandomAccessListIterator<FightingUnit>(attacker.getAttackers());
        final RandomAccessIterator<FightingUnit> dAttackersIt = new RandomAccessListIterator<FightingUnit>(defender.getAttackers());
        do {
            if (aAttackersIt.hasNext()) {
                attack(aAttackersIt, dAttackersIt, defender);
                if (!defender.isAbleToFight()) {
                    return attacker;
                }
            }
            if (dAttackersIt.hasNext()) {
                attack(dAttackersIt, aAttackersIt, attacker);
                if (!attacker.isAbleToFight()) {
                    return defender;
                }
            }
        } while (aAttackersIt.hasNext() || dAttackersIt.hasNext());
        return null;
    }

    protected void attack(final RandomAccessIterator<FightingUnit> aAttackersIt, final RandomAccessIterator<FightingUnit> dAttackersIt, final Army defender) {
        final FightingUnit aAttacker = aAttackersIt.next();
        final List<FightingUnit> victims = defender.getTargets(aAttacker.isSiegeDevice());
        if (!victims.isEmpty()){
            final FightingUnit dTarget = new RandomAccessListIterator<FightingUnit>(victims).next();
            proceedAttack(aAttacker, dTarget);
            if (!dTarget.isAlive()) {
                dAttackersIt.remove(dTarget);
            }
        }
    }

    protected void proceedAttack(final FightingUnit attacker, final FightingUnit defender) {
        final int offensivePoints = attacker.getEffectiveOffense(false);
        final int defensePoints = defender.getEffectiveDefense(false);
        if (getRandom(offensivePoints + defensePoints) <= offensivePoints){
            defender.hit(calculateDamage(attacker));
        }
    }

    protected int calculateDamage(FightingUnit attacker) {
        return attacker.isSiegeDevice() ? getRandom(5) + 5 : 1;
    }

    protected int getRandom(final int seed) {
        return new Random().nextInt(seed);
    }
}